using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace SavedVariablesParser.Line {
    /// <summary>
    /// Represents a line in a World of Warcraft saved variables file that matches the data line format.
    /// </summary>
    public class DataLine : LineBase {
        /// <summary>
        /// 	<para>Initializes an instance of the <see cref="DataLine"/> class.</para>
        /// </summary>
        /// <param name="text">The text of the line.</param>
        /// <param name="type">Specifies the type of line.</param>
        /// <param name="lineNumber">Specifies the line number within the original file where this line can be found.</param>
        /// <exception cref="ArgumentNullException">
        /// 	<para>The argument <paramref name="text"/> is <langword name="null"/>.</para>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// 	<para>The argument <paramref name="text"/> is out of range.</para>
        /// 	<para>-or-</para>
        /// 	<para>The argument <paramref name="lineNumber"/> is out of range.</para>
        /// </exception>
        public DataLine(string text, LineType type, int lineNumber) {
            if (text == null) {
                throw new ArgumentNullException("text");
            }
            if (text.Length == 0) {
                throw new ArgumentOutOfRangeException("text", "The value of 'text' cannot be a zero length string.");
            }
            if (lineNumber <= 0) {
                throw new ArgumentOutOfRangeException("lineNumber", "The value of 'lineNumber' must be greater than zero.");
            }

            base.text = text;
            base.type = type;
            base.lineNumber = lineNumber;
        }

        /// <summary>
        /// Renders the line and returns a string representing the rendered value.
        /// </summary>
        /// <returns>The text line rendered in a predefined format.</returns>
        public override string Render() {
            StringBuilder builder = new StringBuilder();
            this.GenerateDataNode(base.text, builder);
            return builder.ToString();
        }

        /// <summary>
        /// Renders the line to the supplied <see cref="StringBuilder"/>.
        /// </summary>
        /// <param name="builder">The <see cref="StringBuilder"/> to render the string to.</param>
        public override void Render(StringBuilder builder) {
            this.GenerateDataNode(base.text, builder);
        }

        /// <summary>
        /// Generates the data node tag.
        /// </summary>
        /// <param name="line">The line to generate a tag for.</param>
        /// <param name="builder">The <see cref="StringBuilder"/> to render the tag to.</param>
        private void GenerateDataNode(string line, StringBuilder builder) {
            line = base.PurgeTabs(line);

            //<data name="11174:0:0" value="0" />
            builder.Append("<data name=");
            builder.Append("\"");
            builder.Append(this.GetDataKey(line));
            builder.Append("\"");
            builder.Append(" value=");
            builder.Append("\"");
            builder.Append(this.GetDataValue(line));
            builder.Append("\"");
            builder.Append(" />");
            builder.Append(Environment.NewLine);
        }

        /// <summary>
        /// Parses the line of text specified for the key for the data node.
        /// </summary>
        /// <param name="line">The line of text to parse.</param>
        /// <returns>The value that represents the key for the data item.</returns>
        private string GetDataKey(string line) {
            //line = this.PurgeTabs(line);
            line = line.Replace("[", string.Empty).Replace("]", string.Empty).Replace("\"", string.Empty);
            string key = line.Substring(0, line.LastIndexOf("=") - 1);
            return key;
        }

        /// <summary>
        /// Parses the line of text specified for the value for the data node.
        /// </summary>
        /// <param name="line">The line of text to parse.</param>
        /// <returns>The value that represents the value for the data item.</returns>
        private string GetDataValue(string line) {
            //line = base.PurgeTabs(line);
            line = line.Replace("\"", string.Empty).Replace("<br>", Environment.NewLine);
            int equals = line.IndexOf("=") + 2;
            string value = string.Empty;
            
            if (line.LastIndexOf(",") > 0) {
                value = line.Substring(equals, (line.Length - equals) -1);
            } else {
                value = line.Substring(equals, (line.Length - equals));
            }

            // remove or escape forbidden characters.
            return base.EscapeForbiddenCharacters(value);
        }
    }
}
